﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using libmvdkbot;
using System.Threading;
using System.IO;

namespace mvdkbot
{
    public partial class Form1 : Form
    {
        private bool m_bLoopStarted = false;
        Int32 m_vnumber = 0;
        String m_tempReg = String.Empty;
        private DataTable m_dtReg = new DataTable();
        private Thread _thread = null;

        public bool LoopStarted
        {
            get { return m_bLoopStarted; }
            set { m_bLoopStarted = value; }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.m_dtReg = new DataTable();
            m_dtReg.Columns.Add("Reg No.");
            m_dtReg.Columns.Add("Owner Name");
            m_dtReg.Columns.Add("Office");
            m_dtReg.Columns.Add("Maker's Name");
            m_dtReg.Columns.Add("Maker's Classification");
            m_dtReg.Columns.Add("Permanent Address");
            m_dtReg.Columns.Add("Temporary Address");
            m_dtReg.Columns.Add("Issue Date");
            m_dtReg.Columns.Add("Valid Upto");
            m_dtReg.Columns.Add("Seat In All");
            grdInfo.DataSource = this.m_dtReg;
        }

        private void cmbRegion_TextChanged(object sender, EventArgs e)
        {
            String regionCode = cmbRegion.Text.Trim();
            String series = cmbSeries.Text.Trim();
            String number = txtStartNum.Text.Trim();
            btnSearch.Enabled = false;

            if ((String.Empty != regionCode) && (String.Empty != series) &&
                (String.Empty != number) && (4 >= number.Length))
            {
                if (Int32.TryParse(number, out m_vnumber))
                {
                    if (0 < m_vnumber)
                    {
                        btnSearch.Enabled = true;
                        LoopStarted = false;
                        pgBar.Maximum = 9999;
                        pgBar.Minimum = m_vnumber;
                        pgBar.Value = m_vnumber;
                    }
                }
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            Int32 startNum = 0;
            String regionCode = cmbRegion.Text.Trim();
            String series = cmbSeries.Text.Trim();

            if (!LoopStarted)
            {
                SearchParam p = new SearchParam()
                {
                    RegionCode = regionCode,
                    Series = series
                };

                _thread = new Thread(SearchThread);
                _thread.Start(p);
            }
            else
            {
                UpdateLoopState(false);
            }
        }

        private class SearchParam
        {
            public String RegionCode { get; set; }
            public String Series { get; set; }
        }

        private void SearchThread(Object p)
        {
            try
            {
                if (!(p is SearchParam))
                {
                    return;
                }

                UpdateBeginAsync();

                SearchParam sp = p as SearchParam;
                String regionCode = sp.RegionCode;
                String series = sp.Series;
                String secretCode = libmvdkbot.WebEngine.GetScecretCode();
                String tempReg = String.Empty;

                UpdateLoosStateAsync(true);
                TempRegInfo regInfo = null;
                while (LoopStarted)
                {
                    try
                    {
                        tempReg = "KL-" + regionCode + "-" + series + "-TEMP-" + m_vnumber.ToString();
                        UpdateStatusAsync("Checking " + tempReg);

                        regInfo = WebEngine.GetTempRegDetails(regionCode, series, m_vnumber.ToString(), secretCode);
                        AddRowAsync(regInfo);
                        regInfo = null;

                        if (m_vnumber < 1000)
                        {
                            tempReg = "KL-" + regionCode + "-" + series + "-TEMP-0" + m_vnumber.ToString();
                            UpdateStatusAsync("Checking " + tempReg);

                            regInfo = regInfo = WebEngine.GetTempRegDetails(regionCode, series, "0" + m_vnumber.ToString(), secretCode);
                            AddRowAsync(regInfo);
                            regInfo = null;
                        }

                        if (m_vnumber < 100)
                        {
                            tempReg = "KL-" + regionCode + "-" + series + "-TEMP-00" + m_vnumber.ToString();
                            UpdateStatusAsync("Checking " + tempReg);

                            regInfo = WebEngine.GetTempRegDetails(regionCode, series, "00" + m_vnumber.ToString(), secretCode);
                            AddRowAsync(regInfo);
                            regInfo = null;
                        }

                        if (m_vnumber < 10)
                        {
                            tempReg = "KL-" + regionCode + "-" + series + "-TEMP-000" + m_vnumber.ToString();
                            UpdateStatusAsync("Checking " + tempReg);

                            regInfo = WebEngine.GetTempRegDetails(regionCode, series, "000" + m_vnumber.ToString(), secretCode);
                            AddRowAsync(regInfo);
                            regInfo = null;
                        }

                        UpdateTempRegAsync(tempReg);
                        UpdateProgressAsync(m_vnumber);
                        RefreshGridAsync();

                        if (m_vnumber >= 9999)
                        {
                            UpdateLoopState(false);
                            UpdateStatus("Completed");
                            return;
                        }
                        else
                        {
                            m_vnumber++;
                        }
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.Write(ex);
                    }
                }
            }
            finally
            {
                UpdateFinishAsync();
            }
        }

        private void UpdateFinishAsync()
        {
            this.Invoke(new Action(UpdateFinish));
        }

        private void UpdateBeginAsync()
        {
            this.Invoke(new Action(UpdateBegin));
        }

        private void UpdateBegin()
        {
            btnSearch.Text = "Pause";
            pgBar.Visible = true;
            cmbRegion.Enabled = false;
            cmbSeries.Enabled = false;
            txtStartNum.Enabled = false;
        }

        private void UpdateFinish()
        {
            Int32 num = 0;
            Int32.TryParse(txtStartNum.Text.Trim(), out num);
            if ((num == m_vnumber) || (9999 == m_vnumber))
            {
                btnSearch.Text = "Search";
                lblStatus.Text = "";
                pgBar.Visible = false;
                cmbRegion.Enabled = true;
                cmbSeries.Enabled = true;
                txtStartNum.Enabled = true;
            }
            else
            {
                btnSearch.Text = "Resume";
                lblStatus.Text = "Paused After " + m_tempReg;
            }
            _thread = null;
        }

        private void UpdateTempRegAsync(String reg)
        {
            this.Invoke(new Action<String>(UpdateTempReg), new Object[] { reg });
        }

        private void UpdateTempReg(String reg)
        {
            this.m_tempReg = reg;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = LoopStarted;
        }

        private void UpdateProgressAsync(int progress)
        {
            this.Invoke(new Action<int>(UpdateProgress), new Object[] { progress });
        }

        private void UpdateProgress(int progress)
        {
            pgBar.Value = progress;
        }

        private void RefreshGridAsync()
        {
            this.Invoke(new Action(RefreshGrid));
        }

        private void RefreshGrid()
        {
            grdInfo.Update();
        }

        private void UpdateStatusAsync(String status)
        {
            this.Invoke(new Action<String>(UpdateStatus), new Object[] { status });
        }

        private void UpdateStatus(String status)
        {
            lblStatus.Text = status;
        }

        private void AddRowAsync(TempRegInfo reg)
        {
            if (null != reg)
            {
                this.Invoke(new Action<TempRegInfo>(InsertDataRow), new Object[] { reg });
            }
        }

        private void UpdateLoosStateAsync(Boolean started)
        {
            this.Invoke(new Action<Boolean>(UpdateLoopState), new Object[] { started });
        }

        private void UpdateLoopState(Boolean started)
        {
            LoopStarted = started;
        }

        private void InsertDataRow(TempRegInfo reg)
        {
            if(null == reg)
            {
                return;
            }
            DataRow row = m_dtReg.NewRow();
            row["Reg No."] = reg.RegNumber;
            row["Owner Name"] = reg.OwnerName;
            row["Office"] = reg.Office;
            row["Maker's Name"] = reg.MakersName;
            row["Permanent Address"] = reg.PermenentAddress;
            row["Temporary Address"] = reg.TemporaryAddress;
            row["Issue Date"] = reg.IssueDate;
            row["Valid Upto"] = reg.ValidUpTo;
            row["Maker's Classification"] = reg.MakersClass;
            row["Seat In All"] = reg.SeatInAll;
            m_dtReg.Rows.Add(row);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            m_dtReg.Rows.Clear();
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            String clipData = String.Empty;
            String rowData = String.Empty;
            foreach (DataRow row in m_dtReg.Rows)
            {
                rowData = String.Empty ;
                Object[] items = row.ItemArray;
                foreach (Object item in items)
                {
                    rowData = rowData + item.ToString() + "\t";
                }
                rowData = rowData.Trim("\t".ToCharArray());
                clipData = clipData + rowData + "\r\n";
            }
            clipData = clipData.Trim("\r\n".ToCharArray());
            if(String.Empty != clipData)
            {
                Clipboard.SetText(clipData);
            }
        }

        private String GetAsCSV()
        {
            String csvData = String.Empty;
            String rowData = String.Empty;
            foreach (DataColumn col in m_dtReg.Columns)
            {
                String coltext = col.Caption.Replace("\"", "\\\"");
                rowData = rowData + coltext + ",";
            }
            rowData = rowData.Trim(",".ToCharArray());
            csvData = rowData + "\r\n";

            foreach (DataRow row in m_dtReg.Rows)
            {
                rowData = String.Empty;
                Object[] items = row.ItemArray;
                foreach (Object item in items)
                {
                    String columnText = item.ToString();
                    columnText = columnText.Replace("\"", "\\\"");
                    columnText = "\"" + columnText + "\"";
                    rowData = rowData + columnText + ",";
                }
                rowData = rowData.Trim(",".ToCharArray());
                csvData = csvData + rowData + "\r\n";
            }
            csvData = csvData.Trim("\r\n".ToCharArray());
            return csvData;
        }

        private void saveAsCSVToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.FileName = String.Empty;
                sfd.Filter = "Comma Separated Values|*.csv";
                if (DialogResult.OK == sfd.ShowDialog())
                {
                    FileStream fstream = new FileStream(sfd.FileName, FileMode.OpenOrCreate, FileAccess.Write);
                    Byte[] data = Encoding.UTF8.GetBytes(GetAsCSV());
                    fstream.Write(data, 0, data.Length);
                    fstream.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
